package com.naiterui.ehp.bp.domain;

import static javax.persistence.GenerationType.IDENTITY;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang3.StringUtils;

/**
 * 患者实体信息
 *
 * @version 2015年6月18日 上午9:52:05 by Amber
 * @Description 患者持久化信息
 */
@Entity
@Table(name = "patient")
public class Patient implements Serializable {

    /*
     * 患者性别 0：女，1：男，2：未知
     */
    /**
     * 女：<code>GENDER_FEMALE</code>
     */
    public static final int GENDER_FEMALE = 0;
    /**
     * 男：<code>GENDER_MALE</code>
     */
    public static final int GENDER_MALE = 1;
    /**
     * 未知：<code>GENDER_UNKNOWN</code>
     */
    public static final int GENDER_UNKNOWN = 2;


    /**
     * 认证状态-未认证
     */
    public static final int REAL_STATUS_UNAUDIT = 0;

    /**
     * 认证状态-已认证
     */
    public static final int REAL_STATUS_SUCCESS = 1;

    public static final int PATIENT_TYPE_NORMAL = 0;
    public static final int PATIENT_TYPE_TEST = 1;

    /**
     * 关注状态：未关注
     */
    public static final int PATIENT_CALCEL_NO_FOCUS = 0;
    /**
     * 关注状态：已关注
     */
    public static final int PATIENT_CALCEL_NO = 1;
    /**
     * 关注状态：已取消
     */
    public static final int PATIENT_CALCEL_YES = 2;

    private static final long serialVersionUID = 7975217636650981837L;

    private Long id;

    /**
     * 合作方id
     */
    private Long partyUserId;

    /**
     * 姓名：<code>name</code>
     */
    private String name;

    private String openId;

    private String unionId;

    private String miniOpenId;

    /**
     * 性别：<code>gender</code>
     */
    private Integer gender;

    /**
     * 年龄：<code>age</code>
     */
    @Deprecated
    private Integer age;

    /**
     * 城市：<code>cityId</code>
     */
    private Integer cityId;

    /**
     * 电话：<code>phone</code>
     */
    private String phone;

    /**
     * 患者登陆token
     */
    private String token;

    /**
     * 身高：<code>height</code>
     */
    private Integer height;

    /**
     * 体重：<code>weight</code>
     */
    private Integer weight;

    /**
     * 创建时间：<code>createAt</code>
     */
    private Date createAt;

    /**
     * 头像地址（全路径）：<code>headUrl</code>
     */
    private String headUrl;

    /**
     * 昵称：<code>nickName</code>
     */
    private String nickName;

    /**
     * 婚姻状态：<code>maritalStatus</code>
     */
    private Short maritalStatus;

    /**
     * 推荐医生id：<code>recomDoctor</code>
     */
    private Long recomDoctor;

    /**
     * 用户状态 0：正常；1：禁用：<code>accountStatus</code>
     */
    private Integer accountStatus;

    /**
     * 迁移用户id：<code>oldId</code>
     */
    private Integer oldId;

    /**
     * 患者标签 0：默认无标签；1：有效患者标签：<code>labelType</code>
     */
    private Integer labelType = 0;

    /**
     * 注册来源 0：未知；1：自主注册；2：医生推荐；3：DM引流：<code>registSource</code>
     */
    private Integer registSource = 0;

    /**
     * 取消关注公众号状态 0：未知；1：未取消；2：已取消'：<code>cancel</code>
     */
    private Integer cancel = 1;

    /**
     * 取消关注公众号时间
     */
    private Date cancelAt;

    /**
     * 是否新注册用户：true：新注册；false：旧用户<code>newUser</code>
     */
    private Boolean newUser;

    /**
     * 测试帐号状态：0正式，1测试：<code>type</code>
     */
    private Integer type;

    /**
     * 首次上传病历档案标签,0:未上传；1：已上传：<code>firstCaseTag</code>
     */
    private Integer firstCaseTag;
    /**
     * 设备号
     */
    private String deviceSN;
    /**
     * 机型
     */
    private String model;
    /**
     * ip
     */
    private String ip;
    /**
     * 登录地址
     */
    private String loginAddr;

    /**
     * app用户登录的openId
     */
    private String appOpenId;

    /**
     * 身份证号
     */
    private String idCard;
    /**
     * 出生日期
     */
    private Date birthday;
    /**
     * 更新时间
     */
    private Date changedAt;

    /**
     * 认证状态,0:未认证,1:已认证
     */
    private Integer status;

    public Patient() {
        this.createAt = new Date();
        this.accountStatus = 0;
        this.firstCaseTag = 0;
        this.type = Integer.valueOf(0);
    }

    /**
     * @return Boolean 取得域 newUser 的方法。
     */
    @Transient
    public Boolean getNewUser() {
        return this.newUser;
    }

    /**
     * @param newUser 对域 newUser 的设置方法.
     */
    public void setNewUser(Boolean newUser) {
        this.newUser = newUser;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "label_type", nullable = false)
    public Integer getLabelType() {
        return this.labelType;
    }

    public void setLabelType(Integer labelType) {
        this.labelType = labelType;
    }

    @Column(name = "old_id")
    public Integer getOldId() {
        return this.oldId;
    }

    public void setOldId(Integer oldId) {
        this.oldId = oldId;
    }

    @Column(name = "name")
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "open_id", nullable = false)
    public String getOpenId() {
        return this.openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    @Column(name = "union_id", nullable = false)
    public String getUnionId() {
        return this.unionId;
    }

    public void setUnionId(String unionId) {
        this.unionId = unionId;
    }

    @Column(name = "mini_open_id", nullable = false)
    public String getMiniOpenId() {
        return miniOpenId;
    }

    public void setMiniOpenId(String miniOpenId) {
        this.miniOpenId = miniOpenId;
    }

    @Column(name = "gender")
    public Integer getGender() {
        return this.gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    @Column(name = "age", updatable = false)
    //@Transient
    @Deprecated
    public Integer getAge() {
        // 生日不为空，根据生日计算年龄
        // 生日为空，填写年龄不为空，年龄=填写年龄+(当前年份-注册年份)
        int result = 0;
        if (null != this.birthday) {
            result = getAgeByBirth(this.birthday);
            if (0 == result) {
                result = 1;
            }
            return result;
        } else if (null != this.age) {
            Calendar cal = Calendar.getInstance();
            // 当前年份
            int nowYear = cal.get(Calendar.YEAR);
            cal.setTime(this.createAt);
            // 注册年份
            int createYear = cal.get(Calendar.YEAR);
            result = this.age + (nowYear - createYear);
            if (0 == result) {
                result = 1;
            }
            return result;
        }
        return null;
    }

    @Deprecated
    public void setAge(Integer age) {
        this.age = age;
    }

    @Column(name = "city_id")
    public Integer getCityId() {
        return this.cityId;
    }

    public void setCityId(Integer cityId) {
        this.cityId = cityId;
    }

    @Column(name = "phone")
    public String getPhone() {
        return this.phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Column(name = "height")
    public Integer getHeight() {
        return this.height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    @Column(name = "weight")
    public Integer getWeight() {
        return this.weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    @Column(name = "head_url", nullable = false)
    public String getHeadUrl() {
        return this.headUrl;
    }

    public void setHeadUrl(String headUrl) {
        this.headUrl = headUrl;
    }

    @Column(name = "created_at", nullable = false)
    public Date getCreateAt() {
        return this.createAt;
    }

    public void setCreateAt(Date createAt) {
        this.createAt = createAt;
    }

    @Column(name = "nick_name")
    public String getNickName() {
        return this.nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    @Column(name = "marital_status")
    public Short getMaritalStatus() {
        return this.maritalStatus;
    }

    public void setMaritalStatus(Short maritalStatus) {
        this.maritalStatus = maritalStatus;
    }

    @Column(name = "recom_doctor")
    public Long getRecomDoctor() {
        return this.recomDoctor;
    }

    public void setRecomDoctor(Long recomDoctor) {
        this.recomDoctor = recomDoctor;
    }

    @Column(name = "account_status")
    public Integer getAccountStatus() {
        return this.accountStatus;
    }

    public void setAccountStatus(Integer accountStatus) {
        this.accountStatus = accountStatus;
    }

    /**
     * @return Integer 取得域 registSource 的方法。
     */
    @Column(name = "regist_source", nullable = false)
    public Integer getRegistSource() {
        return this.registSource;
    }

    /**
     * @param registSource 对域 registSource 的设置方法.
     */
    public void setRegistSource(Integer registSource) {
        this.registSource = registSource;
    }

    /**
     * @return Integer 取得域 cancel 的方法。
     */
    @Column(name = "cancel", nullable = false)
    public Integer getCancel() {
        return this.cancel;
    }

    /**
     * @param cancel 对域 cancel 的设置方法.
     */
    public void setCancel(Integer cancel) {
        this.cancel = cancel;
    }

    public boolean saveValidate() {
        if (this.unionId == null || this.openId == null || this.createAt == null) {
            return false;
        }
        return true;
    }

    /**
     * @return Integer 取得域 type 的方法。
     */
    @Column(name = "type", nullable = false)
    public Integer getType() {
        return this.type;
    }

    /**
     * @param type 对域 type 的设置方法.
     */
    public void setType(Integer type) {
        this.type = type;
    }

    /**
     * @return Integer 取得域 firstCaseTag 的方法。
     */
    @Column(name = "first_case_tag")
    public Integer getFirstCaseTag() {
        return this.firstCaseTag;
    }

    /**
     * @param firstCaseTag 对域 firstCaseTag 的设置方法.
     */
    public void setFirstCaseTag(Integer firstCaseTag) {
        this.firstCaseTag = firstCaseTag;
    }

    /**
     * 是否可以咨询
     * Patient.cantalk()<BR> <P>Author : Amber </P> <P>Date : 2015年7月24日 </P>
     *
     * @return
     */
    public boolean cantalk() {
        // 个人资料不完善不可以咨询
        // 名称逻辑变更：默认可为空，为空时回显通过微信nickname获取
        // 2.5.2需求--改为姓名，性别，年龄，手机号四项组合判断,全部填写则返回true
        if (StringUtils.isEmpty(this.getPhone()) || StringUtils.isEmpty(this.getName()) || "未知".equals(this.getGenderStr())
                || this.getAge() == null) {
            return false;
        }
        return true;
    }

    /**
     * 获取患者性别
     * Patient.getGenderStr()
     *
     * @return
     *
     * @Date 2016年6月21日
     * @since 2.5.0
     */
    @Transient
    public String getGenderStr() {
        if (null == this.gender) {
            return "未知";
        }
        String genderStr;
        switch (this.gender) {
            case GENDER_FEMALE:
                genderStr = "女";
                break;
            case GENDER_MALE:
                genderStr = "男";
                break;
            case GENDER_UNKNOWN:
                genderStr = "未知";
                break;
            default:
                genderStr = "未知";
                break;
        }
        return genderStr;
    }

    @Column(name = "party_user_id")
    public Long getPartyUserId() {
        return this.partyUserId;
    }

    public void setPartyUserId(Long partyUserId) {
        this.partyUserId = partyUserId;
    }

    @Column(name = "token")
    public String getToken() {
        return this.token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    @Column(name = "device_sn")
    public String getDeviceSN() {
        return this.deviceSN;
    }

    public void setDeviceSN(String deviceSN) {
        this.deviceSN = deviceSN;
    }

    @Column(name = "model")
    public String getModel() {
        return this.model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    @Column(name = "ip")
    public String getIp() {
        return this.ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    @Column(name = "login_addr")
    public String getLoginAddr() {
        return this.loginAddr;
    }

    public void setLoginAddr(String loginAddr) {
        this.loginAddr = loginAddr;
    }

    @Column(name = "app_open_id")
    public String getAppOpenId() {
        return this.appOpenId;
    }

    public void setAppOpenId(String appOpenId) {
        this.appOpenId = appOpenId;
    }

    @Column(name = "id_card")
    public String getIdCard() {
        return this.idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    @Column(name = "birthday")
    public Date getBirthday() {
        return this.birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Column(name = "changed_at")
    public Date getChangedAt() {
        return this.changedAt;
    }

    public void setChangedAt(Date changedAt) {
        this.changedAt = changedAt;
    }

    /**
     * 验证是否包含指定标签
     * Patient.validateLabel()
     *
     * @param label
     *
     * @return
     *
     * @Author fangguanhong
     * @Date 2017年6月24日
     * @since 1.0.0
     */
    public boolean validateLabel(Integer label) {
        if ((this.labelType & label) == label) {
            return true;
        }
        return false;
    }

    @Column(name = "status", nullable = false)
    public Integer getStatus() {
        if (null == this.status) {
            return 0;
        }
        return this.status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    /**
     * 根据出生日期计算年龄
     *
     * @param birthday
     *
     * @return
     */
    private static int getAgeByBirth(Date birthday) {
        int age = 0;
        try {
            Calendar now = Calendar.getInstance();
            now.setTime(new Date());// 当前时间

            Calendar birth = Calendar.getInstance();
            birth.setTime(birthday);

            if (birth.after(now)) {//如果传入的时间，在当前时间的后面，返回0岁
                age = 0;
            } else {
                age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
                if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
                    age -= 1;
                }
            }
            return age;
        } catch (Exception e) {//兼容性更强,异常后返回数据
            return 0;
        }
    }

    @Column(name = "cancel_at")
    public Date getCancelAt() {
        return this.cancelAt;
    }

    public void setCancelAt(Date cancelAt) {
        this.cancelAt = cancelAt;
    }

}
